package main

import (
	"flag"
	"fmt"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/go-ping/ping"
	"github.com/gookit/color"
)

var ipSucess []string

func checkIpInfo(ips string) bool {
	addr := strings.Trim(ips, " ")
	// regStr := `^(([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`
	regStr := `^(([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){2}$`
	if match, _ := regexp.MatchString(regStr, addr); match {
		return true
	}
	return false
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	var ip_net string
	// fmt.Printf("请输入网段(如10.1.203.): ")
	// fmt.Scanln(&b)

	flag.StringVar(&ip_net, "net", "", "请指定网段（网段后注意加点），如 cping -net 10.1.203.")
	// var b = flag.String("net", "network", "for example 10.1.203.")
	flag.Parse()
	// fmt.Printf("网段为%s:", b)

	if checkIpInfo(ip_net) {

		start := time.Now()
		c := make(chan string)
		for i := 0; i < 255; i++ {
			target := ips(ip_net, i)
			// fmt.Println(target)
			// go pingHost(target, c)
			go runCmd(target, c)

		}

		for i := 0; i < 255; i++ {
			<-c

		}

		conDisplay(ipSucess, ip_net)
		// end := time.Now()
		// elapsed := end.Sub(start)
		elapsed := float64(time.Since(start).Seconds())
		// fmt.Printf("\n\n%sonline: %v台\telapsed: %0.2fs", b, len(ipSucess), elapsed)
		fmt.Printf("\n\nonline: %v\telapsed: %0.2fs", len(ipSucess), elapsed)

	} else {
		// fmt.Println("输入信息不正确，请重新输入!")
		flag.Usage()
	}
}

func ips(ip_net string, i int) string {
	target := ip_net + strconv.Itoa(i)
	return target
}

func in(target string, str_array []string) bool {
	for _, element := range str_array {
		if target == element {
			return true
		}
	}
	return false
}

func conDisplay(ips []string, b string) {
	fmt.Printf("cPing ver:20220126\n")
	fmt.Printf("Ping Results Of %v\n\n", b)
	n := 16

	for i := 0; i <= 254; i++ {
		target := strconv.Itoa(i)
		// result := in(target, ips)
		if in(target, ips) {
			color.Green.Printf("  %3.d", i)
		} else {
			// color.Gray.Printf("  %3.d", i)
			color.LightRed.Printf("  %3.d", i)
		}
		if (i+1)%n == 0 {
			fmt.Printf("\n")

		}

	}

}

func runCmd(v string, c chan string) {

	// cmdline := "ping -n 2 -w 5" + " " + v
	// cmd := exec.Command("cmd", "/c", cmdline)
	// cmd.Stdout = os.Stdout
	// if err := cmd.Run(); err != nil {

	// }
	if ServerPing(v) {
		v2 := strings.Split(v, ".")
		ipSucess = append(ipSucess, v2[len(v2)-1])
	}

	c <- v
}

func ServerPing(target string) bool {
	pinger, err := ping.NewPinger(target)
	if err != nil {
		panic(err)
	}
	pinger.Count = 3
	pinger.Timeout = time.Duration(3 * time.Second)
	pinger.SetPrivileged(true)
	pinger.Run() // blocks until finished
	stats := pinger.Statistics()
	// fmt.Println(stats)
	// 有回包，就是说明IP是可用的
	return stats.PacketsRecv >= 1
}
